﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using Pavilion.Communications;

namespace Pavilion.DesignerTool
{
    static class LockTransfer
    {
        static public void Add(LockWrapper lockWrapper)
        {
            LinkWrapper linkWrapperParent = lockWrapper.LinkWrapperParent;
            var resourceName = linkWrapperParent.ContainerWrapperParent.NodeScriptWrapper.ResourceData.ResourceName;
            var scriptName = linkWrapperParent.ContainerWrapperParent.NodeScriptWrapper.Name;

            Add(resourceName, scriptName, linkWrapperParent.ContainerWrapperParent.ContainerNode, linkWrapperParent.Link, lockWrapper.Lock);
        }

        static public void Add(string resourceName, string scriptName, ContainerNode parentContainer, Link link, ILock lockItem)
        {
            var containerNodeNameList = NodeTransfer.CreateNodeStringCollection(parentContainer);
            var linkIndex = parentContainer.LinkCollection.IndexOf(link);
            var assemblyName = lockItem.GetType().Assembly.ManifestModule.FullyQualifiedName;
            var propertyTypeName = lockItem.GetType().FullName;

            DataTransferClient.Instance.TransferData((proxy) => proxy.AddLock(resourceName, scriptName, containerNodeNameList, linkIndex, assemblyName, propertyTypeName));

            PropertyDescriptorCollection propertyDescriptors = TypeDescriptor.GetProperties(lockItem);

            foreach (PropertyDescriptor descriptor in propertyDescriptors)
                Update(resourceName, scriptName, parentContainer, link, lockItem, descriptor);
        }

        static public void Remove(LockWrapper lockWrapper, int lockIndex)
        {
            LinkWrapper linkWrapperParent = lockWrapper.LinkWrapperParent;
            ContainerNodeWrapper containerNodeWrapperParent = linkWrapperParent.ContainerWrapperParent;
            var resourceName = containerNodeWrapperParent.NodeScriptWrapper.ResourceData.ResourceName;
            var scriptName = containerNodeWrapperParent.NodeScriptWrapper.Name;

            Remove(resourceName, scriptName, containerNodeWrapperParent.ContainerNode, linkWrapperParent.Link, lockIndex);
        }

        static public void Remove(string resourceName, string scriptName, ContainerNode parentContainer, Link link, int lockIndex)
        {
            var containerNodeNameList = NodeTransfer.CreateNodeStringCollection(parentContainer);
            var linkIndex = parentContainer.LinkCollection.IndexOf(link);

            DataTransferClient.Instance.TransferData((proxy) => proxy.RemoveLock(resourceName, scriptName, containerNodeNameList, linkIndex, lockIndex));
        }

        static public void Update(LockPropertyItem lockPropertyItem)
        {
            Update(lockPropertyItem.LockWrapperParent, lockPropertyItem.PropertyDescriptor);
        }

        static public void Update(LockWrapper lockWrapper, PropertyDescriptor propertyDiscriptor)
        {
            LinkWrapper linkWrapperParent = lockWrapper.LinkWrapperParent;
            ContainerNodeWrapper containerNodeWrapperParent = linkWrapperParent.ContainerWrapperParent;
            var resourceName = containerNodeWrapperParent.NodeScriptWrapper.ResourceData.ResourceName;
            var scriptName = containerNodeWrapperParent.NodeScriptWrapper.Name;

            Update(resourceName, scriptName, containerNodeWrapperParent.ContainerNode, linkWrapperParent.Link, lockWrapper.Lock, propertyDiscriptor);
        }

        static public void Update(string resourceName, string scriptName, ContainerNode parentContainer, Link link, ILock lockItem, PropertyDescriptor propertyDiscriptor)
        {
            var assemblyName = propertyDiscriptor.PropertyType.Assembly.ManifestModule.FullyQualifiedName;
            var propertyTypeName = propertyDiscriptor.PropertyType.FullName;

            Update(resourceName, scriptName, parentContainer, link, lockItem, propertyDiscriptor.DisplayName, propertyDiscriptor.GetValue(lockItem), assemblyName, propertyTypeName);
        }

        static public void Update(string resourceName, string scriptName, ContainerNode parentContainer, Link link, ILock lockItem, string propertyName, object propertyValue, string assemblyName, string propertyTypeName)
        {
            var containerNodeNameList = NodeTransfer.CreateNodeStringCollection(parentContainer);
            var linkIndex = parentContainer.LinkCollection.IndexOf(link);
            var lockIndex = new List<ILock>(link.LockCollection).IndexOf(lockItem);

            string propertyValueString = null;

            if (propertyValue != null)
                propertyValueString = propertyValue.ToString();

            DataTransferClient.Instance.TransferData((proxy) => proxy.UpdateLockData(resourceName, scriptName, containerNodeNameList, linkIndex, lockIndex, propertyName, propertyValueString, assemblyName, propertyTypeName));
        }
    }
}
